﻿using PaintDotNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace AnimatedGifHandling
{
    public class AnimatedGifFileType : FileType, IFileTypeFactory
    {
        public AnimatedGifFileType()
            : base("Animated Gif", FileTypeFlags.SupportsLoading | FileTypeFlags.SupportsSaving | FileTypeFlags.SupportsLayers, new string[] { ".gif", ".agif" })
        {
        }

        protected override Document OnLoad(System.IO.Stream input)
        {
            Gif.Components.GifDecoder dec = new Gif.Components.GifDecoder();
            var err = dec.Read(input);

            var a = dec.GetFrameSize();

            var doc = new Document(a.Width, a.Height);

            doc.CustomHeaders = string.Format("{0};{1}", dec.GetLoopCount(), dec.GetDelay(0));

            for (int i = 0; i < dec.GetFrameCount(); i++)
            {
                var frame = dec.GetFrame(i);
                var layer = new BitmapLayer(frame.Width, frame.Height);

                layer.Name = "Layer " + (i + 1).ToString();
                layer.Surface.CopyFromGdipBitmap(frame);
                doc.Layers.Add(layer);                
            }

            return doc;
        }

        public FileType[] GetFileTypeInstances()
        {
            return new FileType[]
            {
                this
            };
        }

        protected override void OnSave(Document input, System.IO.Stream output, SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback)
        {
            var anim = new Gif.Components.AnimatedGifEncoder();
            anim.Start(output);

            int loopCount = 0;
            int frameDelay = 500;

            try
            {
                if (!string.IsNullOrEmpty(input.CustomHeaders) && input.CustomHeaders.Contains(';'))
                {
                    var pts = input.CustomHeaders.Split(';');
                    loopCount = int.Parse(pts[0]);
                    frameDelay = int.Parse(pts[1]);
                }
            }
            catch
            {

            }

            var dlf = new AnimatedGifSaveForm();
            dlf.LoopCount = loopCount;
            dlf.FrameDelay = frameDelay;

            dlf.ShowDialog();

            loopCount = dlf.LoopCount;
            frameDelay = dlf.FrameDelay;

            anim.SetRepeat(loopCount);
            anim.SetDelay(frameDelay);

            for (int i = 0; i < input.Layers.Count; i++)
            {
                var layer = input.Layers.GetAt(i);

                if (layer.Visible)
                {
                    layer.Render(new RenderArgs(scratchSurface), layer.Bounds);
                    anim.AddFrame(scratchSurface.CreateAliasedBitmap());
                }
            }

            anim.Finish();
        }
    }
}
